package com.template.app.support;

import java.util.ArrayList;
import java.util.List;

import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.template.app.exception.ErrorException;
import com.template.app.exception.ObjectNotFoundException;
import com.template.app.i18n.I18N;
import com.template.app.model.Response;

public class ControllerHelper {

	public static final String NEW = "new";
	public static final String ADD = "";
	public static final String GET = "{id}";
	public static final String EDIT = "{id}/edit";
	public static final String UPDATE = "{id}";
	public static final String DELETE = "{id}";
	public static final String LIST = "";
	public static final String LIST_BY = "listBy/";
	public static final String SEARCH = "search";
	
	public static final String VIEW_FORM = "/form";
	public static final String VIEW_LIST = "/list";

	public static final String LIST_PARAM = "list";

	public static final String REDIRECT = "redirect:";
	
	public static final String RESPONSE = "response";
	
	public static ModelAndView handleValidationError(String view, BindingResult result) {
		Response response = new Response(Response.VALIDATION_ERROR);
		List<FieldError> errors = result.getFieldErrors();
		
		for (FieldError error : errors) {			
			List<Object> args = new ArrayList<Object>();
			Object[] arguments = error.getArguments();
			for (int i = 0; i < arguments.length; i++) {
				if (arguments[i] instanceof MessageSourceResolvable) {
					args.add(getMessage((MessageSourceResolvable) arguments[i]));
				} else {
					args.add(arguments[i]);
				}
			}
			response.addError(error.getField(), getMessage(error, args.toArray()));
		}
		
//		removeBindingResult(model);
//		model.addAttribute(response);
		
//		redirectAttributes.addFlashAttribute(response);
//		copy(model, redirectAttributes);
				
		ModelAndView mav = new ModelAndView(view, RESPONSE, response);
		return mav;
	}
	
	public static ModelAndView getBaseModelAndView(String view, Class<?> clazz) {
		ModelAndView mav = new ModelAndView(view);
		try {
			mav.addObject(clazz.newInstance());
		} catch (InstantiationException e) {
			throw new ErrorException(e);
		} catch (IllegalAccessException e) {
			throw new ErrorException(e);
		}
		
		return mav;
	}
	
	public static ModelAndView getModelAndView(String view, Object obj) {
		return new ModelAndView(view, "obj", obj);
	}
	
	public static ModelAndView getSuccess(String view) {
		Response response = new Response(Response.SUCCESS);		
		return new ModelAndView(view, RESPONSE, response);
	}
	
	public static String redirect(String to) {
		return REDIRECT + to;
	}

	private static String getMessage(MessageSourceResolvable msr, Object ... args) {
		String msg = msr.getDefaultMessage();
		String[] codes = msr.getCodes();
		for (int i = 0; i < codes.length; i++) {
			try {
				msg = I18N.getString(codes[i], args);					
				break;
			} catch (NoSuchMessageException e) {}
		}
		
		msg = handleExceptionMessage(msg);
		
		return msg;
	}

	private static String handleExceptionMessage(String msg) {
		if (msg.contains(ObjectNotFoundException.class.getName())) {
			msg = getExceptionMessage(msg, ObjectNotFoundException.class);
		}
		return msg;
	}
	
	private static String getExceptionMessage(String msg, Class<? extends Exception> clazz) {
		String className = clazz.getName();
		return msg.substring(msg.indexOf(className) + className.length() + 2);
	}
	
	private static void removeBindingResult(ModelMap model) {		
		for (String s : model.keySet()) {
			if (s.startsWith(BindingResult.MODEL_KEY_PREFIX)) {
				model.remove(s);
				break;
			}
		}
	}
	
	private static void copy(ModelMap model, RedirectAttributes redirectAttributes) {
		for (String s : model.keySet()) {
			redirectAttributes.addFlashAttribute(s, model.get(s));
		}
	}

}
